#include <stdlib.h>
#include "MIApplication.h"
#include "MIUser.h"
#include "MIRole.h"

namespace MIApplication {

int get_role(collaboration::MIApplication* app, const char* role)
{
	unsigned int i;
	collaboration::MIRole* aux;
	
	for(i=0; i<app->roles.length(); i++)
	{
		aux = &(app->roles[i]);
		if (strcmp(aux->name, role) == 0)
		{
			return i;
		}
	}

	return -1;
}

int get_user(collaboration::MIApplication* app, const char* user)
{
	unsigned int i;
	collaboration::MIUser* aux;
	
	for(i=0; i<app->users.length(); i++)
	{
		aux = &(app->users[i]);
		if (strcmp(aux->name, user) == 0)
		{
			return i;
		}
	}

	return -1;
}

int get_component(collaboration::MIApplication* app, const char* comp)
{
	unsigned int i;
	collaboration::MIComponent* aux;
	
	for(i=0; i<app->components.length(); i++)
	{
		aux = &(app->components[i]);
		if (strcmp(aux->name, comp) == 0)
		{
			return i;
		}
	}

	return -1;
}

CORBA::Boolean add_role(collaboration::MIApplication* app, collaboration::MIRole* role)
{
	int len;
	char* role_name = role->name;

	if (get_role(app, role_name) == -1)
	{
		len = app->roles.length();
		app->roles.length(len+1);
		app->roles[len] = *role;
		
		return true;
	}

	else
	{
		return false;
	}
}

CORBA::Boolean remove_role(collaboration::MIApplication* app, const char* role)
{
	unsigned int i;
	collaboration::MIRole* aux;
	collaboration::MIUser* usr;
	collaboration::MIRole* temp;

	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		if (strcmp(usr->default_role, role) == 0)
		{
			return false; //si es rol por defecto no se puede eliminar
		}
	}

	for (i = 0; i < app->roles.length(); i++)
	{
		aux = &(app->roles[i]);
		if (strcmp(aux->name, role) == 0)
		{
			//intercambiar el escogido por el ultimo
			temp = &(app->roles[app->roles.length()-1]);
			app->roles[app->roles.length()-1] = app->roles[i];
			app->roles[i] = *temp;

			//truncar el ultimo elemento
			app->roles.length(app->roles.length()-1);
			
			break;
		}
	}

	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		MIUser::remove_allowed_role(usr, role);
	}

	return true;
}

CORBA::Boolean add_user(collaboration::MIApplication* app, collaboration::MIUser* user)
{
	int len;
	
	if ( (get_user(app, user->name) == -1) &&
		 (get_role(app, user->default_role) != -1) )
	{
		len = app->users.length();
		app->users.length(len+1);
		app->users[len] = *user;
		
		return true;
	}

	else return false;
}

CORBA::Boolean remove_user(collaboration::MIApplication* app, const char* user)
{
	collaboration::MIUser* temp;

	int pos = get_user(app, user);
	if (pos != -1)
	{
		//intercambiar el escogido por el ultimo
		temp = &(app->users[app->users.length()-1]);
		app->users[app->users.length()-1] = app->users[pos];
		app->users[pos] = *temp;
		
		//truncar el ultimo elemento
		app->users.length(app->users.length()-1);
		
		return true;
	}
	else return false;
}

CORBA::Boolean update_user_time(collaboration::MIApplication* app, const char* user)
{
	collaboration::MIUser* aux;
	int pos = get_user(app, user);
	if (pos != -1)
	{
		aux = &(app->users[pos]);
		aux->last_time_updated = time(0);
		app->users[pos] = *aux;
		
		return true;
	}
	else return false;
}

char* set_connected_user(collaboration::MIApplication* app, const char* user)
{
	collaboration::MIUser* aux;
	
	int pos = get_user(app, user);
	if (pos != -1)
	{
		aux = &(app->users[pos]);
		aux->is_online = true;
		aux->actual_role = CORBA::string_dup(aux->default_role);
		
		app->users[pos] = *aux;

		return CORBA::string_dup(aux->actual_role);
	}
	else return NULL;
}

void set_disconnected_user(collaboration::MIApplication* app, const char* user)
{
	collaboration::MIUser* aux;
	
	int pos = get_user(app, user);
	if (pos != -1)
	{
		aux = &(app->users[pos]);
		aux->is_online = false;
		
		app->users[pos] = *aux;
	}
}

void add_component(collaboration::MIApplication* app, collaboration::MIComponent* comp)
{
	int len = app->components.length();
	app->components.length(len+1);
	app->components[len] = *comp;
}

void add_role_component_permissions(collaboration::MIApplication* app, const char* role, const char* comp, CORBA::Long permissions)
{
	int pos = get_role(app, role);
	if (pos != -1)
	{
		MIRole::set_component_permissions(&(app->roles[pos]), comp, permissions);
	}
}

void add_user_component_permissions(collaboration::MIApplication* app, const char* user, const char* comp, CORBA::Long permissions)
{
	int pos = get_user(app, user);
	if (pos != -1)
	{
		MIUser::set_component_permissions(&(app->users[pos]), comp, permissions);
	}
}

CORBA::Long role_component_permissions(collaboration::MIApplication* app, const char* role, const char* comp)
{
	int permiso = -1;
	int pos = get_role(app, role);
	if (pos != -1)
	{
		permiso = MIRole::get_component_permissions(&(app->roles[pos]), comp);
		if (permiso == -1)
			permiso = app->default_permissions;
	}

	return permiso;
}

CORBA::Boolean exists_role(collaboration::MIApplication* app, const char* role)
{
	return (get_role(app, role) != -1);
}

CORBA::Boolean exists_user(collaboration::MIApplication* app, const char* user)
{
	return (get_user(app, user) != -1);
}

CORBA::Boolean exists_component(collaboration::MIApplication* app, const char* comp)
{
	return (get_component(app, comp) != -1);
}

CORBA::Boolean set_actual_user_role(collaboration::MIApplication* app, const char* user, const char* newrole)
{
	int pos_user = get_user(app, user);
	int pos_role = get_role(app, newrole);

	if (pos_user != -1)
	{
		if (pos_role != -1)
		{
			app->users[pos_user].actual_role = CORBA::string_dup(newrole);
			return true;
		}
		else return false;
	}
	else return false;
}

CORBA::Boolean add_user_allowed_role(collaboration::MIApplication* app, const char* user, const char* newrole)
{
	int pos_usr = get_user(app, user);
	int pos_role = get_role(app, newrole);
	
	if (pos_usr != -1)
	{
		if (pos_role != -1)
		{
			return MIUser::add_allowed_role(&(app->users[pos_usr]), newrole);
		}
		else return false;
	}
	else return false;
}

CORBA::Boolean remove_user_allowed_role(collaboration::MIApplication* app, const char* user, const char* role)
{
	int pos = get_user(app, user);
	if (pos != -1)
	{
		return MIUser::remove_allowed_role(&(app->users[pos]), role);
	}
	else return false;
}

collaboration::ListOfUsers* get_non_updated_users(collaboration::MIApplication* app)
{
	collaboration::ListOfUsers* v = new collaboration::ListOfUsers();
	collaboration::MIUser* usr;
	
	long tiempo_margen = 60; //1 minuto de margen
	long tiempo_actual = time(0);
	
	unsigned int len, i;
	
	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		if (usr->is_online && ( ( tiempo_actual - usr->last_time_updated ) > tiempo_margen ))
		{
			len = v->length();
			v->length(len+1);
			(*v)[len] = *usr;
		}
	}

	return v;
}

collaboration::ListOfUserNames* get_role_users(collaboration::MIApplication* app, const char* role)
{
	unsigned int i, len;
	collaboration::ListOfUserNames* conectados = new collaboration::ListOfUserNames();
	collaboration::MIUser* usr;
	
	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		
		if (usr->is_online && (usr->actual_role != NULL)
				&& (strcmp(usr->actual_role, role) == 0))
		{
			len = conectados->length();
			conectados->length(len+1);
			(*conectados)[len] = CORBA::string_dup(usr->name);
		}
	}

	return conectados;
}

collaboration::ListOfUsersAndRoles* get_connected_users(collaboration::MIApplication* app)
{
	unsigned int i, len, len2;
	
	collaboration::ListOfUsersAndRoles* v = new collaboration::ListOfUsersAndRoles();
	collaboration::MIUser* usr;
	
	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		if (usr->is_online)
		{
			len = v->length();
			v->length(len+1);
			
			collaboration::ListOfUserNames* vv = new collaboration::ListOfUserNames();
			len2 = vv->length();
			vv->length(len2+2);
			(*vv)[len2] = CORBA::string_dup(usr->name);
			(*vv)[len2+1] = CORBA::string_dup(usr->actual_role);
			
			(*v)[len] = *vv;
		}
	}

	return v;
}

collaboration::ListOfUsers* get_connected_users_info(collaboration::MIApplication* app)
{
	unsigned int i, len;
	collaboration::ListOfUsers* conectados = new collaboration::ListOfUsers();
	collaboration::MIUser* usr;
	
	for (i = 0; i < app->users.length(); i++)
	{
		usr = &(app->users[i]);
		
		if (usr->is_online)
		{
			len = conectados->length();
			conectados->length(len+1);
			(*conectados)[len] = *usr;
		}
	}

	return conectados;
}

char* get_actual_user_role(collaboration::MIApplication* app, const char* user)
{
	int pos = get_user(app, user);
	if (pos != -1)
	{
		return CORBA::string_dup(app->users[pos].actual_role);
	}
	else return NULL;
}

CORBA::Long user_component_permissions(collaboration::MIApplication* app, const char* user, const char* comp)
{
	int permiso = -1;
	int pos = get_user(app, user);
	
	if (pos != -1)
	{
		permiso = MIUser::get_component_permissions(&(app->users[pos]), comp);
		if (permiso == -1) 
			permiso = app->default_permissions;
	}
	
	return permiso;
}

CORBA::Boolean set_user_component_permissions(collaboration::MIApplication* app, const char* user, const char* comp, CORBA::Long permissions)
{
	int pos_user = get_user(app, user);
	int pos_cmp = get_component(app, comp);
	
	if (( pos_user != -1 ) && ( pos_cmp != -1 ))
	{
		MIUser::set_component_permissions(&(app->users[pos_user]), comp, permissions);
		
		return true;
	}
	else return false;
}

CORBA::Boolean set_role_component_permissions(collaboration::MIApplication* app, const char* role, const char* comp, CORBA::Long permissions)
{
	int pos_role = get_role(app, role);
	int pos_cmp = get_component(app, comp);
	
	if (( pos_role != -1 ) && ( pos_cmp != -1 ))
	{
		MIRole::set_component_permissions(&(app->roles[pos_role]), comp, permissions);
		
		return true;
	}
	else return false;
}

}
